package Factory;

import Clain.SafetyEvent;
import Clain.SafetyHandler;
import Observer.EnvironmentData;
import Observer.EnvironmentObserver;
import Observer.EnvironmentSensorNetwork;
import State.IdleState;
import State.MachineState;
import Strategy.*;

import java.util.Arrays;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class SmartTractor implements AgriculturalMachine, EnvironmentObserver {
    private MachineState state;
    private Coordinate position;
    private double fuelLevel = 100.0; // 油量百分比
    private double workEfficiency = 0.0; // 作业效率
    private double areaCovered = 0.0; // 已覆盖面积(平方米)
    private long startTime = 0; // 开始工作时间
    private long lastUpdateTime = System.currentTimeMillis(); // 上次更新时间
    private Timer autoUpdateTimer;
    private boolean isWorking = false;
    private OperationStrategy currentStrategy;
    private Path currentPath;
    private EnvironmentSensorNetwork sensorNetwork; // 新增：环境传感器网络实例

    public SmartTractor(EnvironmentSensorNetwork sensorNetwork) {
        this.state = new IdleState(this);
        this.position = new Coordinate(0, 0); // 初始位置
        this.currentStrategy =null; // 默认策略
        this.sensorNetwork = sensorNetwork; // 注入环境传感器网络
        sensorNetwork.registerObserver(this); // 注册为观察者
    }

    public void setStrategy(OperationStrategy strategy) {
        this.currentStrategy = strategy;
    }

    @Override
    public void planPath(EnvironmentData data) {
        FieldMap map = new FieldMap();
        PathPlanningStrategy strategy;

        // 获取当前农机实例的引用并创建列表
        List<AgriculturalMachine> machineList = Arrays.asList(this);

        if (map.getObstaclePositions().isEmpty()) {
            strategy = new StandardPathPlanning(data);
        } else {
            // 传递农机列表给构造函数
            strategy = new ObstacleAvoidancePathPlanning(data, machineList);
        }

        PathPlanner planner = new PathPlanner(strategy);
        this.currentPath = planner.planPath(map, data);
        System.out.println("SmartTractor 规划的路径: " + currentPath);
    }

    @Override
    public boolean isWorking() {
        return isWorking;
    }

    @Override
    public void handleSafetyEvent(SafetyEvent event, SafetyHandler safetyHandler) {
        safetyHandler.handle(event);
    }

    @Override
    public double getWorkingWidth() {
        return 2;
    }

    @Override
    public double getSpeed() {
        return 3300.0;
    }

    @Override
    public void update(EnvironmentData data) {
        if (isWorking()) {
            // 优先处理风速异常（对拖拉机影响较大）
            if (data.getWindSpeed() > 20 || data.getWindSpeed() < 2) {
                setStrategy(new WindSpeedStrategy());
            }
            // 其次处理湿度异常
            else if (data.getSoilMoisture() > 0.8 || data.getSoilMoisture() < 0.3) {
                setStrategy(new MoistureStrategy());
            }
            // 最后处理温度异常
            else if (data.getTemperature() > 35 || data.getTemperature() < 5) {
                setStrategy(new TemperatureStrategy());
            }
            // 根据环境数据调整作业效率
            adjustWorkEfficiency(data);
            // 根据环境数据调整路径规划
            planPath(data);
        }
    }

    private void adjustWorkEfficiency(EnvironmentData data) {
        // 根据环境数据调整作业效率的具体逻辑
        // 这里可以根据不同的环境因素设置不同的作业效率调整规则
        if (data.getWindSpeed() > 20) {
            workEfficiency *= 0.8; // 高风速降低作业效率
        } else if (data.getSoilMoisture() < 0.3) {
            workEfficiency *= 0.9; // 低湿度降低作业效率
        }
    }

    @Override
    public void start() {
        System.out.println("拖拉机开始工作");
        state.start();
        startTime = System.currentTimeMillis();
        lastUpdateTime = System.currentTimeMillis();
        isWorking = true; // 启动时设置标志位为true
        if (isWorking) {
            executeTask(); // 执行一次任务
            // 如果提前设置了环境数据，根据数据调整策略
            if (currentStrategy != null) {
                currentStrategy.adjust(this, getCurrentEnvironmentData());
            }
        }
    }
    private EnvironmentData getCurrentEnvironmentData() {
        // 实现获取当前环境数据的逻辑
        if (sensorNetwork != null) {
            return sensorNetwork.getCurrentData(); // 通过传感器网络获取当前环境数据
        }
        return null;
    }

    @Override
    public void stop() {
        System.out.println("拖拉机停止工作");
        state.stop();
        isWorking = false; // 停止时设置标志位为false
    }

    @Override
    public void executeTask() {
        if (isWorking) {
            System.out.println("拖拉机正在执行任务...");
            state.execute();
            // 获取当前环境数据（使用注入的传感器网络实例）
            if (sensorNetwork != null) {
                EnvironmentData data = sensorNetwork.getCurrentData();
                if (data != null) {
                    // 根据环境数据更新策略
                    update(data);
                    // 应用当前策略
                    if (currentStrategy != null) {
                        currentStrategy.adjust(this, data);
                    }
                } else {
                    System.out.println("警告: 环境数据为空，无法调整策略");
                }
            } else {
                System.out.println("错误: 环境传感器网络未初始化");
            }
            // 更新位置、油量等信息
            updatePosition();
            updateFuelLevel();
            updateWorkEfficiency();
            updateAreaCovered();
            lastUpdateTime = System.currentTimeMillis();
        }
    }

    @Override
    public MachineType getType() {
        return MachineType.TRACTOR;
    }

    @Override
    public MachineState getState() {
        return state;
    }

    @Override
    public void setState(MachineState state) {
        this.state = state;
    }

    @Override
    public String getStatusDescription() {
        StringBuilder sb = new StringBuilder();
        sb.append("农机类型: ").append(getType()).append("\n");
        sb.append("当前状态: ").append(state.getStateName()).append("\n");
        sb.append("状态详情: ").append(state.getStateDescription()).append("\n");
        sb.append("位置坐标: (").append(position.getX()).append(", ").append(position.getY()).append(")\n");
        sb.append("油量剩余: ").append(String.format("%.2f", fuelLevel)).append("%\n");
        sb.append("作业效率: ").append(String.format("%.2f", workEfficiency)).append("%\n");
        sb.append("已覆盖面积: ").append(String.format("%.2f", areaCovered)).append("平方米\n");
        sb.append("工作时长: ").append(formatWorkingHours(getWorkingHours())).append("\n");

        // 添加状态警告信息
        if (fuelLevel < 20) {
            sb.append("警告: 油量不足20%，请及时加油!\n");
        }

        return sb.toString();
    }

    // 添加暂停方法
    @Override
    public void pause() {
        state.pause();
        stopAutoUpdate();
    }

    // 添加恢复方法
    @Override
    public void resume() {
        state.resume();
        startAutoUpdate(1); // 每秒更新一次状态
    }

    // 获取工作小时数
    private double getWorkingHours() {
        if (startTime == 0) return 0;
        long currentTime = System.currentTimeMillis();
        return (currentTime - startTime) / (1000.0 * 60 * 60);
    }

    // 格式化工作时长为小时、分钟和秒
    private String formatWorkingHours(double hours) {
        long totalSeconds = (long) (hours * 3600);
        long h = totalSeconds / 3600;
        long m = (totalSeconds % 3600) / 60;
        long s = totalSeconds % 60;
        return String.format("%d小时 %d分钟 %d秒", h, m, s);
    }

    // 更新位置（模拟移动）
    private void updatePosition() {
        long currentTime = System.currentTimeMillis();
        double elapsedHours = (currentTime - lastUpdateTime) / (1000.0 * 60 * 60);
        double speedX = 100; // 每小时X方向移动距离
        double speedY = 100; // 每小时Y方向移动距离
        double newX = position.getX() + speedX * elapsedHours;
        double newY = position.getY() + speedY * elapsedHours;
        position = new Coordinate(newX, newY);
    }

    // 更新油量
    private void updateFuelLevel() {
        long currentTime = System.currentTimeMillis();
        double elapsedHours = (currentTime - lastUpdateTime) / (1000.0 * 60 * 60);
        double hourlyFuelConsumption = 15; // 每小时耗油量
        fuelLevel -= hourlyFuelConsumption * elapsedHours;
        if (fuelLevel < 0) fuelLevel = 0;
    }

    // 更新作业效率
    private void updateWorkEfficiency() {
        long currentTime = System.currentTimeMillis();
        double elapsedHours = (currentTime - lastUpdateTime) / (1000.0 * 60 * 60);
        // 模拟作业效率波动
        workEfficiency = 65 + Math.random() * 35;
    }

    // 更新已覆盖面积
    private void updateAreaCovered() {
        long currentTime = System.currentTimeMillis();
        double elapsedHours = (currentTime - lastUpdateTime) / (1000.0 * 60 * 60);
        double hourlyAreaCovered = 1500; // 每小时覆盖面积
        areaCovered += hourlyAreaCovered * elapsedHours + Math.random() * 100 * elapsedHours;
    }

    @Override
    public void startAutoUpdate(int intervalSeconds) {
        if (autoUpdateTimer != null) {
            autoUpdateTimer.cancel();
        }
        autoUpdateTimer = new Timer();
        autoUpdateTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                executeTask();
            }
        }, 0, intervalSeconds * 1000);
    }

    @Override
    public void stopAutoUpdate() {
        if (autoUpdateTimer != null) {
            autoUpdateTimer.cancel();
            autoUpdateTimer = null;
        }
    }

}
